package com.springapp.persist.interceptor;

import com.springapp.persist.Dialect.Dialect;
import com.springapp.persist.Dialect.MySQL5Dialect;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.naming.ConfigurationException;
import java.sql.Connection;
import java.util.Properties;


@Intercepts(
        {@Signature(type = StatementHandler.class, method = "prepare", args =
                {Connection.class})})
public class PaginationInterceptor implements Interceptor {
    private final static Logger log = LoggerFactory
            .getLogger(PaginationInterceptor.class);

    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statmentHandler = (StatementHandler) invocation
                .getTarget();
        BoundSql boundSql = statmentHandler.getBoundSql();
        MetaObject metaStatementHandler = MetaObject.forObject(statmentHandler,
                new DefaultObjectFactory(), new DefaultObjectWrapperFactory());
        RowBounds rowBounds = (RowBounds) metaStatementHandler
                .getValue("delegate.rowBounds");
        if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
            return invocation.proceed();
        }
        Configuration configuration = (Configuration) metaStatementHandler
                .getValue("delegate.configuration");
        Dialect.Type databaseType = null;
        try {
            databaseType = Dialect.Type.valueOf(configuration.getVariables()
                    .getProperty("dialect").toUpperCase());
        } catch (Exception e) {
            throw new ConfigurationException(
                    "the value of the dialect property in mybatis-config.xml is not defined : "
                            + configuration.getVariables().getProperty(
                            "dialect"));
        }

        Dialect dialect = null;
        switch (databaseType) {
            case MYSQL:
                dialect = new MySQL5Dialect();
            default:
                break;
        }

        String originalSql = (String) metaStatementHandler
                .getValue("delegate.boundSql.sql");
        metaStatementHandler.setValue("delegate.boundSql.sql", dialect
                .getPaginationSql(originalSql, rowBounds.getOffset(),
                        rowBounds.getLimit()));
        metaStatementHandler.setValue("delegate.rowBounds.offset",
                RowBounds.NO_ROW_OFFSET);
        metaStatementHandler.setValue("delegate.rowBounds.limit",
                RowBounds.NO_ROW_LIMIT);
        if (log.isDebugEnabled()) {
            log.debug("生成分页SQL : " + boundSql.getSql());
        }
        return invocation.proceed();
    }

    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    public void setProperties(Properties properties) {
        // TODO Auto-generated method stub
    }
}
